var debug = require('debug')('app:utils:' + process.pid),
    util = require('util'),
    client = require("../controller/redisConn").redisClient,
    async = require('async'),
    _ = require("lodash"),
    settings = require("../config/settings.js"),
    jsonwebtoken = require("jsonwebtoken"),
    errors = require('../exception/exceptionCon').errors;

/**
 *
 * 描述：token验证工具
 *
 * HISTORY
 * ****************************************************************************
 *  ID   DATE           			         PERSON          REASON
 *  1    2015年7月13日 上午11:53:38      Ghold          Create
 * ****************************************************************************
 */
var authCheck = {
    /**
     * 从请求的头部找到Token
     *
     */
    fetch: function(headers) {
        if (headers && headers.authorization) {
            var authorization = headers.authorization;
            var part = authorization.split(' ');
            if (part.length === 2) {
                var token = part[1];
                return part[1];
            } else {
                return part[0];
            }
        } else {
            return null;
        }
    },

    /**
     * 从请求的body找到Token
     *
     */
    fetchFromBody: function(body) {
        if (body && body.authorization) {
            var authorization = body.authorization;
            var part = authorization.split(' ');
            if (part.length === 2) {
                var token = part[1];
                return part[1];
            } else {
                return part[0];
            }
        } else {
            return null;
        }
    },

    /**
     * 创建一个新的Token
     *
     */
    create: function(user, done) {

        debug("Create token");

        if (_.isEmpty(user)) {
            return done(new Error('Invalid Id'), { message: '用户不合法' });
        }

        var data = {
            _id: user._id,
            name: user.name,
            token: jsonwebtoken.sign({ _id: user._id }, settings.auth_secret, {
                expiresInMinutes: settings.token_expiration
            })
        };

        var decoded = jsonwebtoken.decode(data.token);

        data.token_exp = decoded.exp;
        data.token_iat = decoded.iat;

        debug("Token generated for user: %s, token: %s", data.name, data.token);

        async.waterfall([
            function(callback) {
                client.set(data.token, JSON.stringify(data), function(err, reply) {
                    if (err) return callback(err, { message: "缓存异常" });
                    if (!reply) return callback(new Error('Token not set in redis'), { message: "Token没有存入缓存" });
                    client.expire(data.token, settings.token_expiration_sec, function(err, reply) {
                        if (err) return callback(err, { message: "缓存异常" });
                        if (!reply) return callback(new Error('Expiration not set on redis'), { message: "无法设置有效期" });
                        callback(null, data);
                    });
                });
            }
            /*    ,
                function(result, callback){
                    var logonId = "LOGON_" + data._id;
                    client.get(logonId, function(err, reply){
                        if (err) return callback(err, {message: "获取历史登录失败"});
                        if (reply) {
                            client.expire(reply, 0, function (err, reply) {
                                if (err) return callback(err, {message:"缓存异常"});
                                callback(null, logonId);
                            });
                        } else {
                            callback(null, logonId);
                        }
                    });
                },
                function(logonId, callback){
                    client.set(logonId, data.token, function (err, reply) {
                        if (err) return callback(err, {message:"缓存异常"});
                        if (!reply) return callback(new Error('Token not set in redis'), {message:"历史登录没有存入缓存"});
                        client.expire(logonId, settings.token_expiration_sec, function (err, reply) {
                            if (err) return callback(err, {message:"缓存异常"});
                            if (!reply) return callback(new Error('Expiration not set on redis'), {message:"无法设置有效期"});
                            callback(null, data);
                        });
                    });
                }
            */
        ], function(err, result) {
            if (err) return done(err, result);
            done(null, result);
        });
    },

    /**
     * 从缓存中获取Token, 并进行验证
     *
     */
    retrieve: function(token, done) {

        debug("Calling retrieve for token: %s", token);

        if (_.isNull(token)) return done(new Error("token_invalid"), { message: "非法Token" });

        client.get(token, function(err, reply) {
            if (err) return done(err, { "message": "缓存异常" });

            if (_.isNull(reply)) return done(new Error("token_invalid"), { message: "请登录" });
            var data = JSON.parse(reply);
            debug("User data fetched from redis store for user: %s", data.name);

            if (!_.isEqual(data.token, token)) return done(new Error("token_doesnt_exist"), { message: "验证过期，请重新登录" });
            done(null, data);
        });
    },

    /**
     * 除去Token的有效期
     *
     * @param token
     * @returns {boolean}
     */
    expire: function(token, done) {

        debug("Expiring token: %s", token);

        if (token !== null) {
            client.expire(token, 0, function(err, reply) {
                if (err) return done(err, { message: "缓存异常" });
                done(null, reply);
            });
        }
        return token !== null;
    },

    /**
     * 更新token对应的value信息
     *
     * @param token
     * @param user
     */
    updateValue: function(token, user, done) {
        debug("Update token: %s", token);

        if (_.isNull(token)) return done(new Error("token_invalid"), { message: "非法Token" });
        if (_.isEmpty(user)) return done(new Error('Invalid Id'), { message: '用户不合法' });

        var data = {
            _id: user._id,
            name: user.name,
            token: token
        };

        client.set(token, JSON.stringify(data), function(err, reply) {
            if (err) return done(err, { message: "缓存异常" });
            if (!reply) return done(new Error('Token not set in redis'), { message: "Token没有存入缓存" });
            done(null, reply);
        });
    },

    /**
     * 中间件
     *
     */
    middleware: function() {
        var func = function(req, res, next) {
            var token = authCheck.fetch(req.headers);
            if (!token) token = authCheck.fetchFromBody(req.body);
            authCheck.retrieve(token, function(err, data) {
                if (err) {
                    req.user = undefined;
                    return res.render('register', {});
                } else {
                    req.user = data;
                    if (_.includes(data._id, "Anonymous")) {
                        authCheck.expire(token, function(err, reply) {
                            if (err) console.error("删除匿名token失败");
                        });
                    }

                    next();
                }
            });
        };
        func.unless = require("express-unless");
        return func;
    }
};
module.exports.__proto__ = authCheck;

debug("Loaded");
